<!DOCTYPE html>
<html lang="en"><head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1"><!-- Begin Jekyll SEO tag v2.8.0 -->
<title>0055: MVC VIII – Dynamically Loading a TreeView | gtkDcoding</title>
<meta name="generator" content="Jekyll v4.3.4" />
<meta property="og:title" content="0055: MVC VIII – Dynamically Loading a TreeView" />
<meta name="author" content="Ron Tarrant" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="GTK Tutorial on how to dynamically load a TreeView." />
<meta property="og:description" content="GTK Tutorial on how to dynamically load a TreeView." />
<link rel="canonical" href="http://localhost:4000/posts/0055-mvc-viii-dynamically-loading-a-treeview.html" />
<meta property="og:url" content="http://localhost:4000/posts/0055-mvc-viii-dynamically-loading-a-treeview.html" />
<meta property="og:site_name" content="gtkDcoding" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2019-07-23T00:00:00-04:00" />
<meta name="twitter:card" content="summary" />
<meta property="twitter:title" content="0055: MVC VIII – Dynamically Loading a TreeView" />
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"Ron Tarrant"},"dateModified":"2019-07-23T00:00:00-04:00","datePublished":"2019-07-23T00:00:00-04:00","description":"GTK Tutorial on how to dynamically load a TreeView.","headline":"0055: MVC VIII – Dynamically Loading a TreeView","mainEntityOfPage":{"@type":"WebPage","@id":"http://localhost:4000/posts/0055-mvc-viii-dynamically-loading-a-treeview.html"},"url":"http://localhost:4000/posts/0055-mvc-viii-dynamically-loading-a-treeview.html"}</script>
<!-- End Jekyll SEO tag -->
<link rel="stylesheet" href="../assets/main.css">
  <link rel="stylesheet" href="../css/style.css" /><link type="application/atom+xml" rel="alternate" href="http://localhost:4000/feed.xml" title="gtkDcoding" /></head>
<body><header class="site-header" role="banner">

  <div class="wrapper"><a class="site-title" rel="author" href="../">gtkDcoding</a><nav class="site-nav">
        <input type="checkbox" id="nav-trigger" class="nav-trigger" />
        <label for="nav-trigger">
          <span class="menu-icon">
            <svg viewBox="0 0 18 15" width="18px" height="15px">
              <path d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"/>
            </svg>
          </span>
        </label>

        <div class="trigger"><a class="page-link" href="../about.html">About</a><a class="page-link" href="../index-reverse.html">Posts in Date Order</a><a class="page-link" href="../topics.html">Blog Posts by Topic</a></div>
      </nav></div>
</header>
<main class="page-content" aria-label="Content">
      <div class="wrapper">
        <article class="post h-entry" itemscope itemtype="http://schema.org/BlogPosting">
	<header class="post-header">
		<link rel="stylesheet" href="../css/font_size.css" />
		<link rel="stylesheet" href="../css/figure.css" />
		<link rel="stylesheet" href="../css/topics/mvc.css" />  <!-- sub in the tag/topic -->
		<link rel="stylesheet" href="../css/modal.css" />
		<link rel="stylesheet" href="../css/post.css" />
		<link rel="stylesheet" href="../css/mascot_effects.css" />

		
		
		<p class="post-meta">
		<time class="dt-published" datetime="2019-07-23T00:00:00-04:00" itemprop="datePublished">Tuesday, July 23, 2019
		</time>• by <span itemprop="author" itemscope itemtype="http://schema.org/Person"><span class="p-author h-card" itemprop="name">Ron Tarrant</span></span></p>
	</header>

	<div class="post-content e-content" itemprop="articleBody">
		<div class="skew-line"></div>
		<h1 id="0055-mvc-viii--dynamically-loading-a-treeview">0055: MVC VIII – Dynamically Loading a TreeView</h1>

<div class="screenshot-frame">
	<div class="frame-header">
		Results of this example:
	</div>
	<div class="frame-screenshot">
		<figure>
			<img id="img0" src="../images/screenshots/017_mvc/mvc_12.png" alt="Current example output" />		<!-- img# -->
			
			<!-- Modal for screenshot -->
			<div id="modal0" class="modal">																	<!-- modal# -->
				<span class="close0">&times;</span>															<!-- close# -->
				<img class="modal-content" id="img00" />															<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal0");														// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img0");															// img#
			var modalImg = document.getElementById("img00");													// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close0")[0];											// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>
			<figcaption>
			Current example output
			</figcaption>
		</figure>
	</div>

	<div class="frame-terminal">
		<figure class="right">
			<img id="img1" src="../images/screenshots/017_mvc/mvc_12_term.png" alt="Current example terminal output" />		<!-- img#, filename -->

			<!-- Modal for terminal shot -->
			<div id="modal1" class="modal">																				<!-- modal# -->
				<span class="close1">&times;</span>																		<!-- close# -->
				<img class="modal-content" id="img11" />																		<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal1");																	// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img1");																		// img#
			var modalImg = document.getElementById("img11");																// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close1")[0];														// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>

			<figcaption>
				Current example terminal output (click for enlarged view)
			</figcaption>
		</figure>
	</div>

	<div class="frame-footer">																								<!-- ------------- filename (below) --------- -->
		The code file for this example is available <a href="https://github.com/rontarrant/gtkd_demos/blob/master/017_mvc/mvc_12_treeview_font_list.d" target="_blank">here</a>.
	</div>
</div>

<p>This time we’re going to dynamically load the <code class="language-plaintext highlighter-rouge">TreeView</code> with a list of all fonts available on your computer. We’ll use <code class="language-plaintext highlighter-rouge">PgFontDescriptions</code> (<em>Pango</em> fonts) so we can play with not just the names, but the sizes, styles, and weights. And on top of that, we’ll use a bit of math to mix things up and give the list some variety.</p>

<h2 id="a-note-for-windows-users">A Note for Windows Users</h2>

<p>In the <em>Command Prompt</em> window, you may or may not see <em>Pango</em> warnings for a bunch of fonts. They still load and the fonts are certainly usable, so it’s no big deal.</p>

<p>And now, let’s dig in and start by talking about…</p>

<h2 id="the-imports">The Imports</h2>

<p>To get all this working takes a whole mess of imports:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="n">std</span><span class="p">.</span><span class="n">stdio</span><span class="p">;</span>
<span class="k">import</span> <span class="n">std</span><span class="p">.</span><span class="n">math</span><span class="p">;</span>

<span class="k">import</span> <span class="n">gtk</span><span class="p">.</span><span class="n">MainWindow</span><span class="p">;</span>
<span class="k">import</span> <span class="n">gtk</span><span class="p">.</span><span class="n">Main</span><span class="p">;</span>
<span class="k">import</span> <span class="n">gtk</span><span class="p">.</span><span class="n">Widget</span><span class="p">;</span>
<span class="k">import</span> <span class="n">gtk</span><span class="p">.</span><span class="n">Box</span><span class="p">;</span>
<span class="k">import</span> <span class="n">gtk</span><span class="p">.</span><span class="n">ScrolledWindow</span><span class="p">;</span>
<span class="k">import</span> <span class="n">gtk</span><span class="p">.</span><span class="n">TreeView</span><span class="p">;</span>
<span class="k">import</span> <span class="n">gtk</span><span class="p">.</span><span class="n">ListStore</span><span class="p">;</span>
<span class="k">import</span> <span class="n">gtk</span><span class="p">.</span><span class="n">TreeIter</span><span class="p">;</span>
<span class="k">import</span> <span class="n">gtk</span><span class="p">.</span><span class="n">TreePath</span><span class="p">;</span>
<span class="k">import</span> <span class="n">gtk</span><span class="p">.</span><span class="n">TreeViewColumn</span><span class="p">;</span>
<span class="k">import</span> <span class="n">gtk</span><span class="p">.</span><span class="n">CellRendererText</span><span class="p">;</span>
<span class="k">import</span> <span class="n">pango</span><span class="p">.</span><span class="n">PgCairoFontMap</span><span class="p">;</span>
<span class="k">import</span> <span class="n">pango</span><span class="p">.</span><span class="n">PgFontMap</span><span class="p">;</span>
<span class="k">import</span> <span class="n">pango</span><span class="p">.</span><span class="n">PgFontFamily</span><span class="p">;</span>
<span class="k">import</span> <span class="n">pango</span><span class="p">.</span><span class="n">PgFontDescription</span><span class="p">;</span>
</code></pre></div></div>

<p>Now, since the <code class="language-plaintext highlighter-rouge">TreeView</code> and <code class="language-plaintext highlighter-rouge">TreeViewColumn</code>s are pretty much the same as what we’ve done (by now) so many times before, I’ll just comment on things that are different.</p>

<h2 id="fonttreeview-class">FontTreeView Class</h2>

<p>The constructor is very much the same as what we’ve seen before and only departs from that norm with this:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">fontFamilyColumn</span> <span class="p">=</span> <span class="k">new</span> <span class="n">FontFamilyColumn</span><span class="p">(</span><span class="n">fontListStore</span><span class="p">);</span>
<span class="n">appendColumn</span><span class="p">(</span><span class="n">fontFamilyColumn</span><span class="p">);</span>
</code></pre></div></div>

<p>The zeroth column constructor (<code class="language-plaintext highlighter-rouge">FontFamilyColumn</code>) needs access to the <code class="language-plaintext highlighter-rouge">fontListStore</code> so it can pass along data from the <code class="language-plaintext highlighter-rouge">PgFontDescriptions</code> in the Model to its <code class="language-plaintext highlighter-rouge">CellRenderer</code> as it displays the names of the fonts.</p>

<h3 id="the-callback">The Callback</h3>

<p>The other thing that’s done here in the constructor is, we hook up a callback to react whenever the user double-clicks on a cell in the <code class="language-plaintext highlighter-rouge">TreeView</code>. The signal is <code class="language-plaintext highlighter-rouge">onRowActivated</code> and the hook-up is the simple one we’ve used so often:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	<span class="n">addOnRowActivated</span><span class="p">(&amp;</span><span class="n">onRowActivated</span><span class="p">);</span>
</code></pre></div></div>

<p>The purpose of the callback is to report which cell has been clicked and it looks like this:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="n">onRowActivated</span><span class="p">(</span><span class="n">TreePath</span> <span class="n">treePath</span><span class="p">,</span> <span class="n">TreeViewColumn</span> <span class="n">tvc</span><span class="p">,</span> <span class="n">TreeView</span> <span class="n">tv</span><span class="p">)</span>
<span class="p">{</span>
	<span class="kt">int</span> <span class="n">columnNumber</span><span class="p">;</span>
	<span class="n">TreeIter</span> <span class="n">treeIter</span> <span class="p">=</span> <span class="k">new</span> <span class="n">TreeIter</span><span class="p">(</span><span class="n">fontListStore</span><span class="p">,</span> <span class="n">treePath</span><span class="p">);</span>
		
	<span class="c1">// find the column number...</span>
	<span class="k">if</span><span class="p">(</span><span class="n">tvc</span><span class="p">.</span><span class="n">getTitle</span><span class="p">()</span> <span class="p">==</span> <span class="s">"Font Family"</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="n">columnNumber</span> <span class="p">=</span> <span class="mi">0</span><span class="p">;</span>
	<span class="p">}</span>
	<span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="n">tvc</span><span class="p">.</span><span class="n">getTitle</span><span class="p">()</span> <span class="p">==</span> <span class="s">"Size"</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="n">columnNumber</span> <span class="p">=</span> <span class="mi">1</span><span class="p">;</span>
	<span class="p">}</span>
	<span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="n">tvc</span><span class="p">.</span><span class="n">getTitle</span><span class="p">()</span> <span class="p">==</span> <span class="s">"Pango Units"</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="n">columnNumber</span> <span class="p">=</span> <span class="mi">2</span><span class="p">;</span>
	<span class="p">}</span>
	<span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="n">tvc</span><span class="p">.</span><span class="n">getTitle</span><span class="p">()</span> <span class="p">==</span> <span class="s">"Style"</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="n">columnNumber</span> <span class="p">=</span> <span class="mi">3</span><span class="p">;</span>
	<span class="p">}</span>
	<span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="n">tvc</span><span class="p">.</span><span class="n">getTitle</span><span class="p">()</span> <span class="p">==</span> <span class="s">"Weight"</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="n">columnNumber</span> <span class="p">=</span> <span class="mi">4</span><span class="p">;</span>
	<span class="p">}</span>

	<span class="n">writeln</span><span class="p">(</span><span class="s">"TreePath (row): "</span><span class="p">,</span> <span class="n">treePath</span><span class="p">,</span> <span class="s">" columnNumber: "</span><span class="p">,</span> <span class="n">columnNumber</span><span class="p">);</span>
	<span class="n">writeln</span><span class="p">();</span> <span class="c1">// a blank line to separate each report</span>

	<span class="k">auto</span> <span class="n">value</span> <span class="p">=</span> <span class="n">fontListStore</span><span class="p">.</span><span class="n">getValue</span><span class="p">(</span><span class="n">treeIter</span><span class="p">,</span> <span class="n">columnNumber</span><span class="p">);</span>
	<span class="n">writeln</span><span class="p">(</span><span class="s">"cell contains: "</span><span class="p">,</span> <span class="n">value</span><span class="p">.</span><span class="n">getString</span><span class="p">());</span>
</code></pre></div></div>

<p>And here’s what it does:</p>

<ul>
  <li>use the <code class="language-plaintext highlighter-rouge">TreePath</code> to get the row number,</li>
  <li>also using the <code class="language-plaintext highlighter-rouge">TreePath</code>, we create a <code class="language-plaintext highlighter-rouge">TreeIter</code> as a handle for the row data (in other words, the <code class="language-plaintext highlighter-rouge">TreePath</code> gives us the visible row in the <code class="language-plaintext highlighter-rouge">TreeView</code>, the <code class="language-plaintext highlighter-rouge">TreeIter</code> gives us the corresponding row in the <code class="language-plaintext highlighter-rouge">ListStore</code>),</li>
  <li>look up the column number using the column’s header text,</li>
  <li>(purely for informational purposes) echo the row and column numbers to the terminal, and</li>
  <li>use the <code class="language-plaintext highlighter-rouge">TreeIter</code> (which, remember, is a handle for the row where the data is stored), and</li>
  <li>the <code class="language-plaintext highlighter-rouge">columnNumber</code> to grab the value of the specific cell that was clicked.</li>
</ul>

<h2 id="the-fontliststore-class">The FontListStore Class</h2>

<p>This class is a bit different from others we’ve used, starting with the initialization section:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="n">FontListStore</span> <span class="p">:</span> <span class="n">ListStore</span>
<span class="p">{</span>
	<span class="n">SysFontListPango</span> <span class="n">sysFontListPango</span><span class="p">;</span>
	<span class="n">PgFontDescription</span><span class="p">[]</span> <span class="n">fontList</span><span class="p">;</span>
	<span class="n">TreeIter</span> <span class="n">treeIter</span><span class="p">;</span>
	
	<span class="k">enum</span> <span class="n">Column</span>
	<span class="p">{</span>
		<span class="n">FAMILY</span> <span class="p">=</span> <span class="mi">0</span><span class="p">,</span>
		<span class="n">SIZE</span><span class="p">,</span>
		<span class="n">PANGO_SIZE</span><span class="p">,</span>
		<span class="n">STYLE</span><span class="p">,</span>
		<span class="n">WEIGHT</span><span class="p">,</span>
		<span class="n">FONT_DESC</span>
		
	<span class="p">}</span> <span class="c1">// enum Column</span>
</code></pre></div></div>

<p>We’re only working with one array, the <code class="language-plaintext highlighter-rouge">fontList</code> which is an array of <em>Pango</em> font descriptions.</p>

<p>In the <code class="language-plaintext highlighter-rouge">Column</code> <code class="language-plaintext highlighter-rouge">enum</code>, we take advantage of <em>D</em>’s <code class="language-plaintext highlighter-rouge">enum</code> auto-numbering which amounts to: number the first item and <em>D</em> fills in the numbers for the rest automatically.</p>

<h3 id="the-fontliststore-constructor">The FontListStore Constructor</h3>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">this</span><span class="p">()</span>
<span class="p">{</span>
	<span class="k">super</span><span class="p">([</span><span class="n">GType</span><span class="p">.</span><span class="n">STRING</span><span class="p">,</span> <span class="n">GType</span><span class="p">.</span><span class="n">STRING</span><span class="p">,</span> <span class="n">GType</span><span class="p">.</span><span class="n">STRING</span><span class="p">,</span> <span class="n">GType</span><span class="p">.</span><span class="n">STRING</span><span class="p">,</span> <span class="n">GType</span><span class="p">.</span><span class="n">STRING</span><span class="p">,</span> <span class="n">PgFontDescription</span><span class="p">.</span><span class="n">getType</span><span class="p">()]);</span>

	<span class="n">sysFontListPango</span> <span class="p">=</span> <span class="k">new</span> <span class="n">SysFontListPango</span><span class="p">();</span>
	<span class="n">fontList</span> <span class="p">=</span> <span class="n">sysFontListPango</span><span class="p">.</span><span class="n">getList</span><span class="p">();</span>
		
	<span class="k">foreach</span><span class="p">(</span><span class="n">font</span><span class="p">;</span> <span class="n">fontList</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="n">treeIter</span> <span class="p">=</span> <span class="n">createIter</span><span class="p">();</span>
			
		<span class="n">setValue</span><span class="p">(</span><span class="n">treeIter</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">font</span><span class="p">.</span><span class="n">getFamily</span><span class="p">());</span>
		<span class="n">setValue</span><span class="p">(</span><span class="n">treeIter</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">font</span><span class="p">.</span><span class="n">getSize</span><span class="p">()</span> <span class="p">/</span> <span class="mi">1024</span><span class="p">);</span>
		<span class="n">setValue</span><span class="p">(</span><span class="n">treeIter</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="n">font</span><span class="p">.</span><span class="n">getSize</span><span class="p">());</span>
		<span class="n">setValue</span><span class="p">(</span><span class="n">treeIter</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="n">font</span><span class="p">.</span><span class="n">getStyle</span><span class="p">());</span>
		<span class="n">setValue</span><span class="p">(</span><span class="n">treeIter</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="n">font</span><span class="p">.</span><span class="n">getWeight</span><span class="p">());</span>
		<span class="n">setValue</span><span class="p">(</span><span class="n">treeIter</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="n">font</span><span class="p">);</span>
	<span class="p">}</span>

<span class="p">}</span> <span class="c1">// this()</span>
</code></pre></div></div>

<p>I’ll throw in a quick reminder here that  text and numbers are both rendered as strings—which explains the first five <code class="language-plaintext highlighter-rouge">GType</code>s in the array passed to the super-class constructor. But you’ll notice the last item in the array self-identifies using <code class="language-plaintext highlighter-rouge">PgFontDescription.getType()</code>.</p>

<p>Then we:</p>

<ul>
  <li>instantiate a <code class="language-plaintext highlighter-rouge">SysFontListPango</code> object that we’ll look at in a moment,</li>
  <li>get the list of <code class="language-plaintext highlighter-rouge">PgFontDescriptions</code> from it, and</li>
  <li>use the data from each <code class="language-plaintext highlighter-rouge">PgFontDescription</code> in the <code class="language-plaintext highlighter-rouge">foreach()</code> loop to set up the data for the columns.</li>
</ul>

<h2 id="the-sysfontlistpango-class">The SysFontListPango Class</h2>

<p>Here’s the constructor (<em>note: all variables starting with an underscore (_) are private to this class and so is <code class="language-plaintext highlighter-rouge">counter</code></em>):</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">this</span><span class="p">()</span>
<span class="p">{</span>	
	<span class="n">_pgFontMap</span> <span class="p">=</span> <span class="n">PgCairoFontMap</span><span class="p">.</span><span class="n">getDefault</span><span class="p">();</span>
	<span class="n">_pgFontMap</span><span class="p">.</span><span class="n">listFamilies</span><span class="p">(</span><span class="n">_pgFontFamilies</span><span class="p">);</span>

	<span class="n">counter</span> <span class="p">=</span> <span class="mi">1</span><span class="p">;</span>
	
	<span class="k">foreach</span><span class="p">(</span><span class="n">_font</span><span class="p">;</span> <span class="n">_pgFontFamilies</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="n">_fontDesc</span> <span class="p">=</span> <span class="k">new</span> <span class="n">PgFontDescription</span><span class="p">(</span><span class="n">_font</span><span class="p">.</span><span class="n">getName</span><span class="p">(),</span> <span class="n">_fontSize</span><span class="p">);</span>
		<span class="n">_pgFontDescriptions</span> <span class="p">~=</span> <span class="n">_fontDesc</span><span class="p">;</span>

		<span class="k">if</span><span class="p">(</span><span class="n">fmod</span><span class="p">(</span><span class="n">counter</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span> <span class="p">==</span> <span class="mi">0</span><span class="p">)</span>
		<span class="p">{</span>
			<span class="n">varyFontBySize</span><span class="p">();</span>
		<span class="p">}</span>

		<span class="k">if</span><span class="p">(</span><span class="n">fmod</span><span class="p">(</span><span class="n">counter</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span> <span class="p">==</span> <span class="mi">0</span><span class="p">)</span>
		<span class="p">{</span>
			<span class="n">varyFontByWeight</span><span class="p">(</span><span class="n">PangoWeight</span><span class="p">.</span><span class="n">BOLD</span><span class="p">);</span>
		<span class="p">}</span>
		<span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="n">fmod</span><span class="p">(</span><span class="n">counter</span><span class="p">,</span> <span class="mi">6</span><span class="p">)</span> <span class="p">==</span> <span class="mi">0</span><span class="p">)</span>
		<span class="p">{</span>
			<span class="n">varyFontByWeight</span><span class="p">(</span><span class="n">PangoWeight</span><span class="p">.</span><span class="n">THIN</span><span class="p">);</span>
		<span class="p">}</span>

		<span class="n">_fontSize</span><span class="p">++;</span>
		<span class="n">counter</span><span class="p">++;</span>

		<span class="k">if</span><span class="p">(</span><span class="n">_fontSize</span> <span class="p">&gt;</span> <span class="mi">19</span><span class="p">)</span>
		<span class="p">{</span>
				<span class="n">_fontSize</span> <span class="p">=</span> <span class="mi">9</span><span class="p">;</span>
		<span class="p">}</span>
	<span class="p">}</span>

<span class="p">}</span> <span class="c1">// this()</span>
</code></pre></div></div>

<p>We grab a list of fonts from the system and use it to create a <em>Pango</em> <code class="language-plaintext highlighter-rouge">FontMap</code> (referred to as a <code class="language-plaintext highlighter-rouge">PgFontMap</code>). From the <code class="language-plaintext highlighter-rouge">PgFontMap</code> (essentially just a list of font names) the constructor uses a <code class="language-plaintext highlighter-rouge">foreach()</code> loop to create the array of <code class="language-plaintext highlighter-rouge">PgFontDescriptions</code>.</p>

<p>And right in the middle of this, we see why <code class="language-plaintext highlighter-rouge">std.math</code> was imported…</p>

<p>The <code class="language-plaintext highlighter-rouge">fmod()</code> function is used three times so we can make:</p>

<ul>
  <li>every 4th font italics,</li>
  <li>every 5th font heavy (bold), and</li>
  <li>every 6th font light (thin).</li>
</ul>

<p>I’ll leave you to explore the other class functions—<code class="language-plaintext highlighter-rouge">varyFontBySize()</code>, <code class="language-plaintext highlighter-rouge">varyFontByWeight()</code>, and <code class="language-plaintext highlighter-rouge">getList()</code>—which are all straightforward.</p>

<h2 id="reiteration-of-the-font-grabbing-process">Reiteration of the Font-grabbing Process</h2>

<p>Even though this example is about populating a <code class="language-plaintext highlighter-rouge">TreeView</code> on the fly and the font stuff is secondary, I’d feel remiss if I didn’t go over this process in a more linear fashion to make it as clear as possible. Here’s what happens:</p>

<ul>
  <li>in the <code class="language-plaintext highlighter-rouge">SysFontListPango</code> class, we:
    <ul>
      <li>get the default font map from the system using <code class="language-plaintext highlighter-rouge">PgCairoFontMap.getDefault()</code> and</li>
      <li>stuff it into a <code class="language-plaintext highlighter-rouge">PgFontMap</code>,</li>
      <li>then we call <code class="language-plaintext highlighter-rouge">PgFontMap.listFamilies()</code> to stuff this list into a <code class="language-plaintext highlighter-rouge">PgFontFamily</code> array.</li>
      <li>Then—in a <code class="language-plaintext highlighter-rouge">foreach()</code> loop—we use <code class="language-plaintext highlighter-rouge">PgFontFamily.getName()</code> to instantiate an array of <code class="language-plaintext highlighter-rouge">PgFontDescriptions</code>.</li>
    </ul>
  </li>
  <li>That array of <code class="language-plaintext highlighter-rouge">PgFontDescriptions</code> is then accessed by the <code class="language-plaintext highlighter-rouge">FontListStore</code> class to build its model.</li>
  <li>Finally, the <code class="language-plaintext highlighter-rouge">FontTreeView</code> class uses the <code class="language-plaintext highlighter-rouge">FontListStore</code> model to decorate itself.</li>
</ul>

<h2 id="conclusion">Conclusion</h2>

<p>A bit long this time, but it was either go long or break this out into two posts which I really didn’t want to do.</p>

<p>And what we’ve covered—fiddling with fonts in a <code class="language-plaintext highlighter-rouge">ListStore</code>—is really just a precursor for what we’ve got coming next time. We’ll go back to the <code class="language-plaintext highlighter-rouge">ComboBox</code> and do some serious window dressing on it, using images and <code class="language-plaintext highlighter-rouge">PgFontDescriptions</code> to make something really fancy.</p>

<p>Until then, happy computing.</p>

<div class="blog-nav">
	<div style="float: left;">
		<a href="./0054-mvc-vii-treeview-basics.html">Previous: TreeView Basics</a>
	</div>
	<div style="float: right;">
		<a href="./0056-mvc-ix-a-combobox-with-flair.html">Next: A ComboBox with Flair</a>
	</div>
</div>
<p>
	<h3></h3>
<div class="inpage-frame">
	<a href="https://github.com/sponsors/rontarrant">
		<BR>
		<BR>
		<B>Is this article useful? Educational? Entertaining, perhaps?</B>
		<BR>
		<figure class="left">
			<img src="../images/favorite_32.png" alt="Sponsorship heart" style="width: 32px; height: 32px;">
		</figure>
		You're free to accept or decline this invitation to become our newest sponsor.
	</a>
</div>
	<h4 class="comment-blurb"><B>Comments? Questions? Observations?</B></h4>
	<p>
		Did we miss a tidbit of information that would make this post even more informative? Let's talk about it in the comments.
	</p>
	<script src="https://utteranc.es/client.js"
		repo="rontarrant"
		issue-term="pathname"
		theme="github-light"
		crossorigin="anonymous"
		async>
	</script>
	<ul>
		<li> come on over to the <a href="https://forum.dlang.org/">D Language Forum</a> and look for one of the <i>gtkDcoding</i> announcement posts, </li>
		<li> drop by <a href="https://forum.gtkd.org/">the <i>GtkD Forum</i></a>,</li>
		<li> follow the link below to email me, or</li>
		<li> go to the	<a href="https://www.facebook.com">gtkDcoding Facebook page.</a></li>
	</ul>
</p>
<p> You can also subscribe <a href="/feed.xml">via RSS</a> so you won't miss anything. Thank you very much for dropping by.</p>
<p>&copy; Copyright 2025 Ron Tarrant </p>
</div>

	<a class="u-url" href="./0055-mvc-viii-dynamically-loading-a-treeview.html" hidden></a>
</article>

      </div>
    </main><footer class="site-footer h-card">
  <data class="u-url" href="/"></data>

  <div class="wrapper">

    <h2 class="footer-heading">gtkDcoding</h2>

    <div class="footer-col-wrapper">
      <div class="footer-col footer-col-1">
        <ul class="contact-list">
          <li class="p-name">Ron Tarrant</li><li><a class="u-email" href="mailto:gtkDcoding@gmail.com">gtkDcoding@gmail.com</a></li></ul>
      </div>

      <div class="footer-col footer-col-2"><ul class="social-media-list"><li><a href="https://github.com/rontarrant"><svg class="svg-icon"><use xlink:href="../assets/minima-social-icons.svg#github"></use></svg> <span class="username">rontarrant</span></a></li></ul>
</div>

      <div class="footer-col footer-col-3">
        <p>Simple examples of how to use GtkD to build GUI applications.</p>
      </div>
    </div>

  </div>

</footer>
</body>

</html>
